#include "Test.h"

Test::Test(int numFactors) {
  size = numFactors;
  newPairs = 0; // this variable starts at 0 and is incremented whenever a new value is stored in the Test using set_Factor_Value
  std::vector<int>::iterator it;
  for (int i=0; i<numFactors; i++) {
    testArray.push_back (-1); // initialize each item in the testArray to -1
  }
}

void Test::clear() {
  //  std::cout <<"Clearing Test" << std::endl;
  newPairs = 0;
  for (int i=0; i<size; i++) {
    testArray[i] = -1;
  }
}

void Test::print () {
  std::cout <<"Test Generated: ";
  for (int i=0; i<size; i++) {
    std::cout << testArray[i] << " ";
  }
  std::cout << std::endl;
}

// Do NOT change the test array OR hashTable in this function
// Main will have to save the max number of pairs, it's factor, and it's value
// Then when the selection for that factor is made, main will call set_Factor_Value
int Test::test_Factor_Value (int factor, int value, int *hashTable) {
  if (factor > size) return 0;

  int numOfNewPairs = 0;
  for (int i=0; i<size; i++) {
    if (testArray[i] == -1 || i == factor) continue;
    else {
      // Else see if the pair value and testArray[i] are a new pair
      // If they are a new pair, then increment number of pairs
      // if (hash(value, testArray[i]) == true) numOfPairs++;
      uint32_t hashA;
      uint32_t hashB;
      if (value > testArray[i]) {
        hashA = testArray[i];
        hashB = value;
      }
      else {
        hashA = value;
        hashB = testArray[i];
      }

      uint64_t hashResult = encode ((uint32_t)hashA, (uint32_t)hashB);
#ifdef PRINT_ENCODE_ON
      std::cout << "H(" << value << ", " << testArray[i] << ") = " << hashResult << std::endl;
#endif
      if (hashTable[hashResult] == 0) {
        //      std::cout << "Pair found on " << value << ", " << testArray[i] << std::endl;
        numOfNewPairs++;
      }
    }
  }

  return numOfNewPairs;
}

void Test::set_Factor_Value (int factor, int value, int *hashTable) {
  if (factor > size) return;
  testArray[factor] = value; // add the value to its corresponding factor in the testArray
  // traverse the test array
  for (int i=0; i<size; i++) { // now update the hashTable and increment the newPairs counter
    if (testArray[i] == -1 || i == factor) continue; // if the value of the index is -1, it hasn't been set yet
    else {

      uint32_t hashA;
      uint32_t hashB;
      if (value > testArray[i]) {
        hashA = testArray[i];
        hashB = value;
      }
      else {
        hashA = value;
        hashB = testArray[i];
      }

      uint64_t hashResult = encode ((uint32_t)hashA, (uint32_t)hashB); // compute the hash value
      //      std::cout << "Hash Result " << hashResult << std::endl;
      if (hashTable[hashResult] == 0) {
        hashTable[hashResult] = 1; // if the value of the corresponding hashResult in the hashTable is 0, then it is a new pair
#ifdef PRINT_ENCODE_ON
	std::cout << "New Pair detected on pair (" << value << ", " << testArray[i] << ") = ";
	std::cout << "H(" << value << ", " << testArray[i] << ") = " << hashResult << std::endl;
#endif
        newPairs++; // so increment the newPairs counter
      }
      else {
#ifdef PRINT_COLLISION_STATEMENT_ON
	std::cout << "Collision detected on pair (" << value << ", " << testArray[i] << ") = " << hashResult << std::endl;
#endif
      }
    }
  }
}
